package org.chen;

import org.chen.pool.JedisConnect;

public class BitmapsJedisTest {
  public static void main(String[] args) {
    JedisConnect connect = new JedisConnect();
    connect.execute(jedis -> {
      jedis.flushDB();

      //Bitmaps的存储是只以0和1两种状态进行存储的
      //它类似于一个矩阵，二维数组:[[1],[0],[1],[0]]这样的格式
      //里面的值只能是1和0

      //存
      jedis.setbit("sign", 0, true);
      jedis.setbit("sign", 1, "0");
      jedis.setbit("sign", 2, "1");
      jedis.setbit("sign", 3, true);
      jedis.setbit("sign", 4, true);
      jedis.setbit("sign", 5, false);
      jedis.setbit("sign", 6, true);

      //获取key中某个位置的值
      System.out.println(jedis.getbit("sign", 2));//true

      //统计key中1的个数
      System.out.println(jedis.bitcount("sign"));//5

      //零存整取：以位存，取出是字符串
      //如通过存二进制码存Java字符串
      // Java二进制码是：01001010，01100001，01110110，01100001
      jedis.setbit("str", 1, true);
      jedis.setbit("str", 4, true);
      jedis.setbit("str", 6, true);
      jedis.setbit("str", 9, true);
      jedis.setbit("str", 10, true);
      jedis.setbit("str", 15, true);
      jedis.setbit("str", 17, true);
      jedis.setbit("str", 18, true);
      jedis.setbit("str", 19, true);
      jedis.setbit("str", 21, true);
      jedis.setbit("str", 22, true);
      jedis.setbit("str", 25, true);
      jedis.setbit("str", 26, true);
      jedis.setbit("str", 31, true);
      System.out.println(jedis.get("str"));

      //获取Java字符串范围是Ja字符的二进制中1的个数,bitcount中的strat和end指的是字符串中的字符下标的起始
      System.out.println(jedis.bitcount("str", 0, 1));//6

      //在字符串中字符指定范围(可省略)的字符二进制中第一个被设置为0/1的位置
      jedis.bitpos("str", true);

      //整存零取：存字符串，取字符串二进制对应的的位
      //0110 0001,0110 0010
      jedis.set("b1", "ab");
      System.out.println(jedis.getbit("b1", 0));
      System.out.println(jedis.getbit("b1", 1));
      System.out.println(jedis.getbit("b1", 2));
      System.out.println(jedis.getbit("b1", 3));
      System.out.println(jedis.getbit("b1", 4));
      System.out.println(jedis.getbit("b1", 5));
      System.out.println(jedis.getbit("b1", 6));
      System.out.println(jedis.getbit("b1", 7));

      System.out.println(jedis.getbit("b1", 8));
      System.out.println(jedis.getbit("b1", 9));
      System.out.println(jedis.getbit("b1", 10));
      System.out.println(jedis.getbit("b1", 11));
      System.out.println(jedis.getbit("b1", 12));
      System.out.println(jedis.getbit("b1", 13));
      System.out.println(jedis.getbit("b1", 14));
      System.out.println(jedis.getbit("b1", 15));


    //获取b1中的位，从0开始获取，获取4个位，返回一个无符号数字
      //0110 0001,0110 0010
      //从0开始取无符号4位：0110=4+2=6
      System.out.println(jedis.bitfield("b1", "get","u4","0"));//[6]
      //从0开始取有符号4个位，有符号中0代表整数，1代表负数，所以0110是正6
      System.out.println(jedis.bitfield("b1", "get","i4","0"));//[6]
      //从1开始取有符号4个位:1100,1开头是负数，所以是0100=4，所以是-4
      System.out.println(jedis.bitfield("b1", "get","i4","1"));//[-4]
      //批量获取
      System.out.println(jedis.bitfield("b1", "get","u4","0","get","u4","1",
        "get","i4","0","get","i4","1"));//[6, 12, 6, -4]

      //用99的8位无符号二进制数，替换字符串二进制从第8位开始的8位bit
      jedis.bitfield("b1","set","u8","8","99");
      System.out.println(jedis.get("b1"));//ac

      //自增及溢出处理
      //默认溢出清0或取负
      //0110 0001，对第6位开始的2位自增1，即01+1=10=b
      jedis.bitfield("b1","incrby","u2","6","1");
      System.out.println(jedis.get("b1"));//ac
      //10+1=11
      jedis.bitfield("b1","incrby","u2","6","1");
      //11+1，溢出了，清零，即从第6位开始的两位为00，结果是0110 0000
      // redis默认自增溢出采取WRAP: 回环算法，即上溢从最负的负数开始取数，127溢出为-128，下溢则从最大的正数开始取数，即清0
      jedis.bitfield("b1","incrby","u2","6","1");
      System.out.println(jedis.get("b1"));//`c

      jedis.set("b1","ac");
      //FAIL:失败算法,采取溢时不做任何改变
      System.out.println(jedis.bitfield("b1", "overflow","fail", "incrby", "u2"
        , "6", "1"));//[2]
      System.out.println(jedis.get("b1"));//bc
      System.out.println(jedis.bitfield("b1", "overflow","fail", "incrby",
        "u2", "6", "1"));//[3]
      System.out.println(jedis.get("b1"));//cc
      System.out.println(jedis.bitfield("b1", "overflow","fail", "incrby",
        "u2", "6", "1"));//[null]
      System.out.println(jedis.get("b1"));//cc

      jedis.set("b1","cc");
      //SAT: 饱和算法，下溢之后设为最小的整型值，上溢之后设为最大的整数值。即溢出保留在最大/小值
      System.out.println(jedis.bitfield("b1", "overflow","sat", "incrby",
        "u2", "6", "1"));//[3]
      System.out.println(jedis.get("b1"));//cc

    });
  }
}
